/*
 * Jenny Ruppen 09-730-391
 * Sebastien Goldberg 08-914-855
 * Henry Raymond 08-928-061
 * Stefan Mussato 09-752-270
 */
 
package ch.uzh.ifi.sopra.gruppe9.game;

import java.util.ArrayList;

import ch.uzh.ifi.sopra.gruppe9.game.Scenery.Location;

import com.jme3.math.Vector3f;
import com.jme3.scene.Node;


/**
 * Interactive in-game screen of the construction authority.
 */
public class ConstructionAuthorityInterface extends Node {
	
	
	/**
	 * Private class used for the arrows showing to the player where he can insert a new tower element into an existing tower.
	 */
	private class CanInsertElementHere {
		
		/**
		 * Index of the existing tower.
		 */
		private int towerIndex;
		
		/**
		 * Index of the element within the tower.
		 */
		private int elementIndex;
		
		/**
		 * ID of the element that the player wants to insert.
		 */
		private int newElementId;
		
		/**
		 * Quad of the arrow symbol.
		 */
		private GuiQuad symbol;
		
		/**
		 * Interactive surface used to click.
		 */
		private GuiInteractiveArea click; 
		
		/**
		 * Constructor
		 */
		public CanInsertElementHere(Vector3f position, int towerIndex, int elementIndex, int newElementId) {
			this.towerIndex = towerIndex;
			this.elementIndex = elementIndex;
			this.newElementId = newElementId;
			
			int positionX = (int) (position.x / GUI.getPixelScale()) + 32;
			int positionY = 768 - 12 - (int) (position.y / GUI.getPixelScale());
			
			symbol = new GuiQuad();
			symbol.setPositionSize(GUI.Offset.WINDOW, positionX, positionY, 25, 25, 91);
			symbol.setMaterial(MaterialManager.getArrow(), 0.0f, 0.0f, 1.0f, 1.0f);
			canInsertElementHereNode.attachChild(symbol.create());
			
			click = new GuiInteractiveArea(GUI.Offset.WINDOW, positionX, positionY, 25, 25);
			click.setAction(new ICallback() {
				public void run() {
					doAction();
				}
			});
			canInsertElementHereClickables.add(click);
		}
		
		/**
		 * Performs the action.
		 */
		private void doAction() {
			insertElement(towerIndex, elementIndex, newElementId);
		}
	}
	
	
	/**
	 * List of all registered mouseOver event elements of the construction authority.
	 */
	private ArrayList<IMouseOverable> mouseOverables = new ArrayList<IMouseOverable>();
	
	
	/**
	 * List of all registered click event elements of the construction authority.
	 */
	private ArrayList<IClickable> clickables = new ArrayList<IClickable>();
	
	
	/**
	 * List of all registered mouseOver event elements of the construction window.
	 */
	private ArrayList<IMouseOverable> constructionWindowMouseOverables = new ArrayList<IMouseOverable>();
	
	
	/**
	 * List of all registered click event elements of the construction window.
	 */
	private ArrayList<IClickable> constructionWindowClickables = new ArrayList<IClickable>();
	
	
	/**
	 * Color constraint flag of the construction authority
	 */
	private GuiQuad colorConstraintIcon;
	
	
	/**
	 * Text telling player that it's not his turn
	 */
	private GuiText notYourTurn;

	
	/**
	 * Choose number of tower elements to be built button.
	 */
	private GuiButton chooseNumber;
	
	
	/**
	 * Insert tower element button
	 */
	private GuiButton insertElement;
	
	
	/**
	 * Build new tower button
	 */
	private GuiButton newTower;
	
	
	/**
	 * Finish tower construction button
	 */
	private GuiButton finishConstruction;
	
	
	/**
	 * Close window button
	 */
	private GuiButton close;
	
	
	/**
	 * Selection of the number of tower elements the player wants to build.
	 */
	private GuiSelection numberOfElements;
	
	
	/**
	 * Parent node of all buying agents in the building authority.
	 */
	private Node buyingAgentsNode;
	
	
	/**
	 * Window where the player can choose which buying agent he wants to use.
	 */
	private BuyingAgentInterface buyingAgentInterface;
	
	
	/**
	 * Window where the player can choose the number of tower elements he wants to build.
	 */
	private Node numberOfElementsWindow;
	
	
	/**
	 * Window where the player can build tower elements and new towers.
	 */
	private Node constructionWindow;
	
	
	/**
	 * Parent node of all tower elements in the construction selections.
	 */
	private Node towerElementsNode;
	
	
	/**
	 * Selection of middle and window tower elements the player can build.
	 */
	private GuiSelection middleAndWindowElements;
	
	
	/**
	 * Selection of new towers the player can build.
	 */
	private GuiSelection newTowerSelection;
	
	
	/**
	 * Number of elements that the player can still build.
	 */
	private int numberOfElementsLeft = 0;
	
	
	/**
	 * Text telling player how many elements he can still build
	 */
	private GuiText numberOfElementsLeftText;
	
	
	/**
	 * Temporary list of towers the player is currently building.
	 */
	private ArrayList<Tower> previewTowers;
	
	
	/**
	 * Temporary inventory of the player while he is building towers.
	 */
	private ArrayList<TowerElement> previewInventory;
	
	
	/**
	 * List of all arrows showing the player where he can insert a tower element into an existing tower.
	 */
	private ArrayList<CanInsertElementHere> canInsertElementHereArrows = new ArrayList<CanInsertElementHere>();
	
	
	/**
	 * Parent node of all arrows showing the player where he can insert a tower element into an existing tower.
	 */
	private Node canInsertElementHereNode;
	
	
	/**
	 * List of clickable elements for the arrows showing the player where he can insert a tower element.
	 */
	private ArrayList<IClickable> canInsertElementHereClickables = new ArrayList<IClickable>();
	
	
	/**
	 * Constructor: Creates geometry.
	 */
	public ConstructionAuthorityInterface() {
		
		numberOfElementsWindow = new Node();
		constructionWindow = new Node();
		
		GuiWindow window = new GuiWindow(GUI.Offset.SCENE, 29, 30, 710, 610, 50);
		numberOfElementsWindow.attachChild(window);
		
		GuiText title = new GuiText("Baubeh\u00F6rde", Fonts.getLarge());
		title.setPositionSize(GUI.Offset.SCENE, (768 - (int)title.getLineWidth()) / 2, 60, 51);
		numberOfElementsWindow.attachChild(title);
		
		colorConstraintIcon = new GuiQuad();
		colorConstraintIcon.setPositionSize(GUI.Offset.SCENE, 349, 140, 80, 30, 51);
		colorConstraintIcon.setMaterial(MaterialManager.getColorConstraintFlags(), 0.0f, 0.0f, 1.0f, 0.2f);
		colorConstraintIcon.create();
		

		numberOfElements = new GuiSelection(true, false);
		
		for(int i = 0; i < 7; i++) {
			numberOfElements.addOption(i, GUI.Offset.SCENE, (384 - 240) + (i * 70), 220, 60, 90, 52);
			
			GuiQuad icon = new GuiQuad();
			icon.setPositionSize(GUI.Offset.SCENE, (384 - 240) + (i * 70), 220, 60, 90, 53);
			icon.setMaterial(MaterialManager.getConstructionIcons(), 0.125f * i, 0.0f, 0.125f, 1.0f);
			numberOfElementsWindow.attachChild(icon.create());
			
			GuiSlot slot = new GuiSlot(GUI.Offset.SCENE, (384 - 230) + (i * 70), 330, 40, 75, 51);
			numberOfElementsWindow.attachChild(slot);	
		}

		numberOfElementsWindow.attachChild(numberOfElements);
		numberOfElements.setAction(new ICallback() {
			public void run() { 
				if(numberOfElements.getValue() == -1) {
					chooseNumber.setActive(false);
				} else {
					chooseNumber.setActive(true);
				}
			}
		});
		
		buyingAgentsNode = new Node();
		numberOfElementsWindow.attachChild(buyingAgentsNode);
		
		chooseNumber = new GuiButton("Turmteile bauen");
		chooseNumber.setPositionSize(GUI.Offset.SCENE, (768 - 220) / 2, 465, 220, 51);
		chooseNumber.setAction(new ICallback() { 
			public void run() {
				chooseNumber.setActive(false);
				close.setActive(false);
				GUI.unregisterMouseOverable(mouseOverables);
				GUI.unregisterClickable(clickables);

				if(Game.board().getSeason() < 4) {
					buyingAgentInterface = new BuyingAgentInterface(false, Game.board().getConstructionAuthority().getColorConstraint());
				} else {
					buyingAgentInterface = new BuyingAgentInterface(true, Game.board().getConstructionAuthority().getColorConstraint());
				}

				buyingAgentInterface.setCancelAction(new ICallback() { 
					public void run() {
						chooseNumber.setActive(true);
						close.setActive(true);
						GUI.registerMouseOverable(mouseOverables);
						GUI.registerClickable(clickables);
					}
				});
				buyingAgentInterface.setCarryOutActionAction(new ICallback() {
					public void run() {
						showConstructionWindow();
					}
				});
			}
		});
		chooseNumber.create();
		chooseNumber.setActive(false);
		numberOfElementsWindow.attachChild(chooseNumber);
		
		notYourTurn = new GuiText("Du bist nicht am Zug.");
		notYourTurn.setPositionSize(GUI.Offset.SCENE, (768 - (int)notYourTurn.getLineWidth()) / 2, 470, 51);
		
		close = new GuiButton("Schliessen");
		close.setPositionSize(GUI.Offset.SCENE, (768 - 160) / 2, 555, 160, 51);
		close.setAction(new ICallback() { 
			public void run() { 
				GUI.changeState(GuiState.State.CLEAN_INGAME_SCREEN);
			}
		});
		numberOfElementsWindow.attachChild(close.create());
		
		clickables.add(chooseNumber);
		clickables.add(close);
		clickables.addAll(numberOfElements.getClickables());
		
		mouseOverables.add(chooseNumber);
		mouseOverables.add(close);
		mouseOverables.addAll(numberOfElements.getMouseOverables());
		
		
		// Construction window
		
		constructionWindow = new Node();
		
		GuiWindow constructionWindowWindow = new GuiWindow(GUI.Offset.SCENE, 359, 30, 380, 708, 60);
		constructionWindow.attachChild(constructionWindowWindow);
		
		numberOfElementsLeftText = new GuiText("Verbleibende Baubewilligungen: 7");
		numberOfElementsLeftText.setPositionSize(GUI.Offset.SCENE, 389, 60, 61);
		constructionWindow.attachChild(numberOfElementsLeftText);
		
		GuiText buildElementText = new GuiText("Mittelteile und Fenster:");
		buildElementText.setPositionSize(GUI.Offset.SCENE, 389, 100, 61);
		constructionWindow.attachChild(buildElementText);
		
		GuiText buildTowerText = new GuiText("Basisteile und Spitzen:");
		buildTowerText.setPositionSize(GUI.Offset.SCENE, 389, 395, 61);
		constructionWindow.attachChild(buildTowerText);

		towerElementsNode = new Node();
		constructionWindow.attachChild(towerElementsNode);
		
		middleAndWindowElements = new GuiSelection(true, false);
		
		newTowerSelection = new GuiSelection(true, false);
		
		insertElement = new GuiButton("Turmteil einbauen");
		insertElement.setPositionSize(GUI.Offset.SCENE, 549 - 100, 325, 200, 61);
		insertElement.setAction(new ICallback() { 
			public void run() {
				showInsertElementSelection(middleAndWindowElements.getValue());
			}
		});
		constructionWindow.attachChild(insertElement.create());
		insertElement.setActive(false);
		
		newTower = new GuiButton("Neuer Turm bauen");
		newTower.setPositionSize(GUI.Offset.SCENE, 549 - 100, 595, 200, 61);
		newTower.setAction(new ICallback() { 
			public void run() {
				Tower newTowerObject = new Tower();
				newTowerObject.assemble((newTowerSelection.getValue() / 1000) + "," + (newTowerSelection.getValue() % 1000));
				previewTowers.add(newTowerObject);
				Scenery.previewMyTowers(previewTowers);
				numberOfElementsLeft -= 2;
				ArrayList<TowerElement> newPreviewInventory = new ArrayList<TowerElement>();
				for(TowerElement element : previewInventory) {
					if(element.getId() != (newTowerSelection.getValue() / 1000) && element.getId() != (newTowerSelection.getValue() % 1000)) {
						newPreviewInventory.add(element);
					}
				}
				previewInventory = newPreviewInventory;
				updateConstructionWindow();
			}
		});
		constructionWindow.attachChild(newTower.create());
		newTower.setActive(false);
		
		
		finishConstruction = new GuiButton("Bau abschliessen");
		finishConstruction.setPositionSize(GUI.Offset.SCENE, 549 - 100, 668, 200, 61);
		finishConstruction.setAction(new ICallback() { 
			public void run() {
				
				String instructions = "";
				
				for(Tower previewTower : previewTowers) {
					instructions += previewTower.getInstructions() + ";";
				}
				if(instructions.substring(instructions.length() - 1).equals(";")) {
					instructions = instructions.substring(0, instructions.length() - 1);
				}
				
				int[] buyingAgentIDs = buyingAgentInterface.getBuyingAgents();
				
				boolean success = false;
				success = Game.board().getConstructionAuthority().doAction(Game.board().getMyIndex(), buyingAgentIDs[0], buyingAgentIDs[1], numberOfElements.getValue(), instructions);
						
				if(!success) {
					System.err.println("Error while executing construction authority action.");
					return;
				}
				GUI.changeState(GuiState.State.CLEAN_INGAME_SCREEN);
			}
		});
		constructionWindow.attachChild(finishConstruction.create());
		
		canInsertElementHereNode = new Node();
		constructionWindow.attachChild(canInsertElementHereNode);

		constructionWindowClickables.add(insertElement);
		constructionWindowClickables.add(newTower);
		constructionWindowClickables.add(finishConstruction);
		
		constructionWindowMouseOverables.add(insertElement);
		constructionWindowMouseOverables.add(newTower);
		constructionWindowMouseOverables.add(finishConstruction);
	}
	
	
	/**
	 * Show construction window.
	 */
	private void showConstructionWindow() {
		
		numberOfElementsLeft = numberOfElements.getValue() + 1;
		previewTowers = Game.board().me().getTowers();
		previewInventory = Game.board().me().getInventory();
		
		if(Game.board().getPlayerNum() == 2) {
			if(Game.board().getMyIndex() == 0) {
				Scenery.startCamAnimation(Location.BUILDING_LOT_2_1, null);
			} else if(Game.board().getMyIndex() == 1) {
				Scenery.startCamAnimation(Location.BUILDING_LOT_2_2, null);
			}
		} else if(Game.board().getPlayerNum() == 3) {
			if(Game.board().getMyIndex() == 0) {
				Scenery.startCamAnimation(Location.BUILDING_LOT_3_1, null);
			} else if(Game.board().getMyIndex() == 1) {
				Scenery.startCamAnimation(Location.BUILDING_LOT_3_2, null);
			} else if(Game.board().getMyIndex() == 2) {
				Scenery.startCamAnimation(Location.BUILDING_LOT_3_3, null);
			}
		} else if(Game.board().getPlayerNum() == 4) {
			if(Game.board().getMyIndex() == 0) {
				Scenery.startCamAnimation(Location.BUILDING_LOT_4_1, null);
			} else if(Game.board().getMyIndex() == 1) {
				Scenery.startCamAnimation(Location.BUILDING_LOT_4_2, null);
			} else if(Game.board().getMyIndex() == 2) {
				Scenery.startCamAnimation(Location.BUILDING_LOT_4_3, null);
			} else if(Game.board().getMyIndex() == 3) {
				Scenery.startCamAnimation(Location.BUILDING_LOT_4_4, null);
			}
		}
		
		this.detachChild(numberOfElementsWindow);
		this.attachChild(constructionWindow);
		
		updateConstructionWindow();
	}
	
	
	/**
	 * Updates the selections in the construction window.
	 */
	private void updateConstructionWindow() {
		
		GUI.unregisterClickable(constructionWindowClickables);
		GUI.unregisterMouseOverable(constructionWindowMouseOverables);
		
		towerElementsNode.detachAllChildren();
		
		numberOfElementsLeftText.setText("Verbleibende Baubewilligungen: " + numberOfElementsLeft);
		
		if(constructionWindow.hasChild(middleAndWindowElements)) {
			constructionWindowClickables.removeAll(middleAndWindowElements.getClickables());
			constructionWindowMouseOverables.removeAll(middleAndWindowElements.getMouseOverables());
			constructionWindow.detachChild(middleAndWindowElements);
		}
		
		middleAndWindowElements = new GuiSelection(true, false);
		middleAndWindowElements.setAction(new ICallback() {
			public void run() { 
				if(middleAndWindowElements.getValue() == -1) {
					insertElement.setActive(false);
				} else {
					insertElement.setActive(true);
				}
			}
		});
		constructionWindow.attachChild(middleAndWindowElements);
		
		boolean[] hasTowers = {false, false, false, false, false}; // brown, green, red, black, white
		
		for(Tower playerTower : previewTowers) {
			if(playerTower.getMaterial() == TowerElement.Material.BROWN) {
				hasTowers[0] = true;
			} else if(playerTower.getMaterial() == TowerElement.Material.GREEN) {
				hasTowers[1] = true;
			} else if(playerTower.getMaterial() == TowerElement.Material.RED) {
				hasTowers[2] = true;
			} else if(playerTower.getMaterial() == TowerElement.Material.BLACK) {
				hasTowers[3] = true;
			} else if(playerTower.getMaterial() == TowerElement.Material.WHITE) {
				hasTowers[4] = true;
			}
		}
		
		ArrayList<TowerElement> middleAndwindow = new ArrayList<TowerElement>();
		ArrayList<TowerElement> baseAndRoof = new ArrayList<TowerElement>();
		
		for(TowerElement inventoryElement : previewInventory) {
			if(inventoryElement.getType() == TowerElement.Type.MIDDLE || inventoryElement.getType() == TowerElement.Type.WINDOW) {
				middleAndwindow.add(inventoryElement);
			} else {
				baseAndRoof.add(inventoryElement);
			}
		}
		
		int numberOfElements = middleAndwindow.size();
		for(int i = 0; i < numberOfElements; i++) {
			int xOffset = 389 + 65 * (i % 5);
			int yOffset = 125 + 65 * (i / 5);
			
			TowerElement element = middleAndwindow.get(i);
			
			middleAndWindowElements.addOption(element.getId(), GUI.Offset.SCENE, xOffset, yOffset, 60, 60, 62);
				
			GuiTowerElement guiElement = new GuiTowerElement(element);
			towerElementsNode.attachChild(guiElement.get2D(GUI.Offset.SCENE, xOffset + 30, yOffset + 43, 63, 1.0f));
			
			if(numberOfElementsLeft < 1) {
				middleAndWindowElements.deactivate(element.getId());
			} else if(element.getMaterial() == TowerElement.Material.BROWN && !hasTowers[0]) {
				middleAndWindowElements.deactivate(element.getId());
			} else if(element.getMaterial() == TowerElement.Material.GREEN && !hasTowers[1]) {
				middleAndWindowElements.deactivate(element.getId());
			} else if(element.getMaterial() == TowerElement.Material.RED && !hasTowers[2]) {
				middleAndWindowElements.deactivate(element.getId());
			} else if(element.getMaterial() == TowerElement.Material.BLACK && !hasTowers[3]) {
				middleAndWindowElements.deactivate(element.getId());
			} else if(element.getMaterial() == TowerElement.Material.WHITE && !hasTowers[4]) {
				middleAndWindowElements.deactivate(element.getId());
			}
		}
		constructionWindowClickables.addAll(middleAndWindowElements.getClickables());
		constructionWindowMouseOverables.addAll(middleAndWindowElements.getMouseOverables());
		
		insertElement.move(GUI.Offset.SCENE, 549 - 100, 195 + 65 * (numberOfElements / 5), 61);
		
		ArrayList<TowerElement> possibleNewTowers = new ArrayList<TowerElement>();
		
		for(TowerElement baseElement : baseAndRoof) {
			if(baseElement.getType() == TowerElement.Type.BASE) {
				for(TowerElement roofElement : baseAndRoof) {
					if(roofElement.getType() == TowerElement.Type.ROOF && baseElement.getMaterial() == roofElement.getMaterial()) {
						boolean towerTypeAlreadyInSelection = false;
						for(int i = 0; i < possibleNewTowers.size(); i += 2) {
							if(possibleNewTowers.get(i).getMaterial() == baseElement.getMaterial() &&
							   possibleNewTowers.get(i).isGolden() == baseElement.isGolden() &&
							   possibleNewTowers.get(i + 1).getMaterial() == roofElement.getMaterial() &&
							   possibleNewTowers.get(i + 1).isGolden() == roofElement.isGolden()) {
								towerTypeAlreadyInSelection = true;
							}
						}
						if(!towerTypeAlreadyInSelection) {
							possibleNewTowers.add(baseElement);
							possibleNewTowers.add(roofElement);
						}
					}
				}
			}
		}
		
		if(constructionWindow.hasChild(newTowerSelection)) {
			constructionWindowClickables.removeAll(newTowerSelection.getClickables());
			constructionWindowMouseOverables.removeAll(newTowerSelection.getMouseOverables());
			constructionWindow.detachChild(newTowerSelection);
		}
		
		newTowerSelection = new GuiSelection(true, false);
		newTowerSelection.setAction(new ICallback() {
			public void run() { 
				if(newTowerSelection.getValue() == -1) {
					newTower.setActive(false);
				} else {
					newTower.setActive(true);
				}
			}
		});
		constructionWindow.attachChild(newTowerSelection);
		
		int numberOfTowers = possibleNewTowers.size() / 2;
		for(int i = 0; i < numberOfTowers; i++) {
			int xOffset = 389 + 81 * (i % 4);
			int yOffset = 420 + 85 * (i / 4);
			
			TowerElement base = possibleNewTowers.get(i * 2);
			TowerElement roof = possibleNewTowers.get((i * 2) + 1);
			
			newTowerSelection.addOption(base.getId() * 1000 + roof.getId(), GUI.Offset.SCENE, xOffset, yOffset, 76, 80, 62);
				
			GuiTowerElement guiBaseElement = new GuiTowerElement(base);
			towerElementsNode.attachChild(guiBaseElement.get2D(GUI.Offset.SCENE, xOffset + 38, yOffset + 66, 63, 1.0f));
			
			GuiTowerElement guiRoofElement = new GuiTowerElement(roof);
			towerElementsNode.attachChild(guiRoofElement.get2D(GUI.Offset.SCENE, xOffset + 38, yOffset + 41, 63, 1.0f));
			
			if(numberOfElementsLeft < 2) {
				newTowerSelection.deactivate(base.getId() * 1000 + roof.getId());
			}
			
		}
		constructionWindowClickables.addAll(newTowerSelection.getClickables());
		constructionWindowMouseOverables.addAll(newTowerSelection.getMouseOverables());
		
		newTower.move(GUI.Offset.SCENE, 549 - 100, 510 + 85 * (numberOfTowers / 4), 61);
		
		GUI.registerClickable(constructionWindowClickables);
		GUI.registerMouseOverable(constructionWindowMouseOverables);
		
		insertElement.setActive(false);
		newTower.setActive(false);
		finishConstruction.setActive(true);
	}
	
	
	/**
	 * Show the selection of locations where a tower element can be inserted into an existing tower.
	 */
	public void showInsertElementSelection(int towerElementId) {
		TowerElement chosenElement = new TowerElement(0);
		ArrayList<TowerElement> newPreviewInventory = new ArrayList<TowerElement>();
		for(TowerElement element : previewInventory) {
			if(element.getId() == towerElementId) {
				chosenElement = element;
			} else {
				newPreviewInventory.add(element);
			}
		}
		previewInventory = newPreviewInventory;
		
		insertElement.setActive(false);
		newTower.setActive(false);
		finishConstruction.setActive(false);
		middleAndWindowElements.deactivateAll();
		newTowerSelection.deactivateAll();
		
		for(int towerIndex = 0; towerIndex < previewTowers.size(); towerIndex++) {
			Tower previewTower = previewTowers.get(towerIndex);
			if(previewTower.getMaterial() == chosenElement.getMaterial()) {
				for(int elementIndex = 1; elementIndex < previewTower.getHeight(); elementIndex++) {
					Vector3f arrowPosition = Scenery.get2dPosition(Scenery.getTowerElementPosition(Game.board().getMyIndex(), towerIndex, previewTower, elementIndex));
					CanInsertElementHere arrow = new CanInsertElementHere(arrowPosition, towerIndex, elementIndex, chosenElement.getId());
					canInsertElementHereArrows.add(arrow);
				}
			}
		}
		GUI.registerClickable(canInsertElementHereClickables);
	}
	
	
	/**
	 * Inserts an chosen tower element at a specific point in e specific tower.
	 */
	private void insertElement(int towerIndex, int elementIndex, int newElementId) {
		Tower oldTower = previewTowers.get(towerIndex);
		String newInstructions = "";
		for(int i = 0; i < elementIndex; i++) {
			newInstructions += oldTower.getElements().get(i).getId() + ",";
		}
		newInstructions += newElementId;
		for(int i = elementIndex; i < oldTower.getElements().size(); i++) {
			newInstructions += "," + oldTower.getElements().get(i).getId();
		}
		
		Tower newTowerObject = new Tower();
		newTowerObject.assemble(newInstructions);
		previewTowers.set(towerIndex, newTowerObject);
		Scenery.previewMyTowers(previewTowers);
		numberOfElementsLeft--;
		updateConstructionWindow();
		
		canInsertElementHereNode.detachAllChildren();
		GUI.unregisterClickable(canInsertElementHereClickables);
		canInsertElementHereClickables.clear();
		canInsertElementHereArrows.clear();
	}
	
	
	/**
	 * Attach all needed geometry and register all mouseOver and click events.
	 */
	public void show() {
		Scenery.startCamAnimation(Location.CONSTRUCTION_AUTHORITY, new ICallback() {
			public void run() {
				GUI.getConstructionAuthority().attachChild(numberOfElementsWindow);
				GUI.registerMouseOverable(mouseOverables);
				GUI.registerClickable(clickables);
		
				GUI.getConstructionAuthority().updateConstructionAuthority();
			}
		});
	}
	
	
	/**
	 * Detach all geometry and unregister all mouseOver and click events.
	 */
	public void hide() {
		if(this.hasChild(numberOfElementsWindow)) {
			this.detachChild(numberOfElementsWindow);
			GUI.unregisterMouseOverable(mouseOverables);
			GUI.unregisterClickable(clickables);
		}
		if(this.hasChild(constructionWindow)) {
			this.detachChild(constructionWindow);
			GUI.unregisterMouseOverable(constructionWindowMouseOverables);
			GUI.unregisterClickable(constructionWindowClickables);
		}
		Scenery.startCamAnimation(Location.BASIC_SCENE_CAMERA, null);
	}


	/**
	 * Updates content of the construction authority window.
	 */
	public void updateConstructionAuthority() {
		numberOfElements.clearSelection();
		middleAndWindowElements.clearSelection();
		newTowerSelection.clearSelection();
		close.setActive(true);
		
		BuyingAgent.Color colorConstraint = Game.board().getConstructionAuthority().getColorConstraint();
		if(colorConstraint == BuyingAgent.Color.NONE && numberOfElementsWindow.hasChild(colorConstraintIcon)) {
			numberOfElementsWindow.detachChild(colorConstraintIcon);
		}
		if(colorConstraint != BuyingAgent.Color.NONE && !numberOfElementsWindow.hasChild(colorConstraintIcon)) {
			numberOfElementsWindow.attachChild(colorConstraintIcon);
		}
		
		if(colorConstraint == BuyingAgent.Color.BLUE) {
			colorConstraintIcon.changeTextureCoords(0.0f, 0.0f, 1.0f, 0.2f);
		} else if(colorConstraint == BuyingAgent.Color.GREEN) {
			colorConstraintIcon.changeTextureCoords(0.0f, 0.2f, 1.0f, 0.2f);
		} else if(colorConstraint == BuyingAgent.Color.ORANGE) {
			colorConstraintIcon.changeTextureCoords(0.0f, 0.4f, 1.0f, 0.2f);
		} else if(colorConstraint == BuyingAgent.Color.PURPLE) {
			colorConstraintIcon.changeTextureCoords(0.0f, 0.6f, 1.0f, 0.2f);
		} else if(colorConstraint == BuyingAgent.Color.YELLOW) {
			colorConstraintIcon.changeTextureCoords(0.0f, 0.8f, 1.0f, 0.2f);
		}
		
		int[] useOfSlots = Game.board().getConstructionAuthority().getBuyingAgentSlots();
		buyingAgentsNode.detachAllChildren();
		for(int i = 0; i < 7; i++) {
			if(useOfSlots[i] == 1) {
				buyingAgentsNode.attachChild(GuiBuyingAgent.getColor2D(colorConstraint, GUI.Offset.SCENE, (384 - 230) + (i * 70), 330, 52));
			} else if(useOfSlots[i] == 2) {
				buyingAgentsNode.attachChild(GuiBuyingAgent.getColor2D(BuyingAgent.Color.NONE, GUI.Offset.SCENE, (384 - 230) + (i * 70), 330, 52));
			}
		}
		
		if(Game.board().getTurn() == Game.board().getMyIndex()) {
			if(numberOfElementsWindow.hasChild(notYourTurn)) {
				numberOfElementsWindow.detachChild(notYourTurn);
			}
			if(!numberOfElementsWindow.hasChild(chooseNumber)) {
				numberOfElementsWindow.attachChild(chooseNumber);
			}
			numberOfElements.activateAll();
			for(int i = 0; i < 7; i++) {
				if(useOfSlots[i] == 1) {
					numberOfElements.deactivate(i);
				} else if(useOfSlots[i] == 2) {
					numberOfElements.deactivate(i);
				}
			}
		} else {
			if(!numberOfElementsWindow.hasChild(notYourTurn)) {
				numberOfElementsWindow.attachChild(notYourTurn);
			}
			if(numberOfElementsWindow.hasChild(chooseNumber)) {
				numberOfElementsWindow.detachChild(chooseNumber);
			}
			numberOfElements.deactivateAll();
		}
	}
	
}
